//-----------------------------------------------------------------------------
// Name: zombiemain.cpp
// Auth: Bradford J. Smith & Robert Darty
//-----------------------------------------------------------------------------

#include "Assert.h"
#include "Display.h"
#include "DisplayManager.h"
#include "Input.h"
#include "RobTown.h"
#include "AnimateObject.h"
#include "AnimateObjectManager.h"
#include "InanimateObject.h"
#include "InanimateObjectManager.h"
#include "Systems.h"
#include "InputManager.h"
#include "corona/corona.h"
#include "BulletManager.h"
#include "GunManager.h"
#include "BoundingManager.h"
#include "rifle.h"
#include "shotgun.h"
#include "Vaccine.h"
#include <cstdlib>
#include <gl/glut.h>
#include <gl/freeglut_ext.h>
#include <time.h>
#include "barn.h"
#include "DeadHuman.h"
#include "DeadCow.h"

//-----------------------------------------------------------------------------
// Globals:
//-----------------------------------------------------------------------------
//corona::Image* gpWheelImageData;

//-----------------------------------------------------------------------------
// Function Prototypes:
//-----------------------------------------------------------------------------
void Initialize();
void InitObjects();
void ShutdownObjects();
void InitDisplay();
void ShutdownDisplay();

//-----------------------------------------------------------------------------
// Desc: The main function of this programs serves to setup OpenGL, initialize
//			the program, set up all the callback functions, and start the 
//			event loop.
int main(int argc, char* argv[])
{
	// Initialize OpenGL

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(kInitialWindowWidth, kInitialWindowHeight);
	glutInitWindowPosition(0, 0);

	glutCreateWindow("Braaaaaiiiiiins!!!!!");

// Call the program specific initialization
	Initialize();

	// Set up all of the callback functions.
	glutReshapeFunc(ReshapeFunction);
	glutKeyboardFunc(KeyDownFunction);
	glutKeyboardUpFunc(KeyUpFunction);
	glutDisplayFunc(DisplayFunction);
	glutSpecialFunc(SpecialKeyDownFunction);
	glutSpecialUpFunc(SpecialKeyUpFunction);
	glutIdleFunc(DisplayFunction);
	glutPassiveMotionFunc(MouseMoveFunction);
	glutMotionFunc(MouseMoveFunction);
	glutMouseFunc(MouseClickFunc);
	glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);

	glutWarpPointer(kInitialWindowWidth/2, kInitialWindowHeight/2);
	InitSystems();
	InitDisplay();
	InitObjects();

	// Start the event processing loop.
	glutMainLoop();

	ShutdownDisplay();
	ShutdownObjects();
	ShutdownSystems();

	return 0;
}

void InitObjects()
{
	srand( (unsigned int)time(NULL));
	//Setup Maangers and guns
	cBulletManager* pBulletManager = new cBulletManager;
	cDisplayManager* pDisplayManager = GetDisplayManager();
	//adds guns for player
	cGunManager* pGunManager = new cGunManager;
	{
		cGunManager* pGunManager = GetGunManager();
		pGunManager->addGun(1, false, Vaccine);
		pGunManager->addGun(5, true, Rifle);
		pGunManager->addGun(4, false, Shotgun);

		
		pDisplayManager->SetInitBullets(pGunManager->GetBullets());
	}
	//creates the guns
	cRifle* pRifle = new cRifle;
	cShotgun* pShotgun = new cShotgun;
	cVaccine* pVaccine = new cVaccine;

	cInanimateObjectManager* pInanimateObjectManager = GetInanimateObjectManager();
	
	//Setup bullet Image
	pDisplayManager->SetupBulletImage();

	//Draw trees
	pInanimateObjectManager->AddInanimateObject(kTree, 20.0f, 0.0f, -220.0f );

	pInanimateObjectManager->AddInanimateObject(kTree, 20.0f, 0.0f, -195.0f );

	pInanimateObjectManager->AddInanimateObject(kTree, -20.0f, 0.0f, -195.0f );

	pInanimateObjectManager->AddInanimateObject(kTree, -20.0f, 0.0f, -220.0f );

	pInanimateObjectManager->AddInanimateObject(kPalmTree, -98.0f, 0.0f, 140.0f );

	pInanimateObjectManager->AddInanimateObject(kPalmTree, -98.0f, 0.0f, 224.0f );

	pInanimateObjectManager->AddInanimateObject(kPalmTree, -130.0f, 0.0f, 224.0f );

	//for ( int k = 115; k < 167; k +=20 )
	//{
	//	pInanimateObjectManager->AddInanimateObject(kTree, (float)k, 0.0f, -30.0f );
	//}

	
	//Outer Walls  (letter codes for my own reference)
	pInanimateObjectManager->AddInanimateObjectFence(kFence, 0.0f, -245.0f, 30.0f, 5.0f); //A

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -72.5f, -215.0f, 42.5f, 35.0f); //B

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -65.0f, -165.0f, 50.0f, 15.0f); //C

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -182.5f, -175.0f, 67.5f, 75.0f); //D

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -232.5f, -10.0f, 17.5f, 90.0f); //E

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -205.0f, 105.0f, 45.0f, 25.0f); //F

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -210.0f, 180.0f, 40.0f, 50.0f); //G

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -160.0f, 240.0f, 90.0f, 10.0f); //H

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 30.0f, 230.0f, 100.0f, 20.0f); //I

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 190.0f, 205.0f, 60.0f, 45.0f); //J

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 205.0f, 70.0f, 45.0f, 20.0f); //K

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 225.0f, 125.0f, 25.0f, 35.0f); //Ka

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 230.0f, 0.0f, 20.0f, 50.0f); //L

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 227.5f, -150.0f, 22.5f, 100.0f); //M

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 160.0f, -225.0f, 45.0f, 25.0f); //N

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 72.5f, -215.0f, 42.5f, 35.0f); //O

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 65.0f, -165.0f, 50.0f, 15.0f); //P

	//Inner walls (letter codes for my own reference)

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 30.0f, -110.0f, 115.0f, 11.0f); //Q

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 160.0f, -135.0f, 15.0f, 35.0f); //R

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 127.5f, -75.0f, 47.5f, 25.0f); //S

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 95.0f, 0.0f, 15.0f, 50.0f); //T

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 105.0f, 90.0f, 25.0f, 40.0f); //U

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 150.0f, 125.0f, 20.0f, 5.0f); //V

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 70.0f, 155.0f, 30.0f, 25.0f); //W

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 60.0f, 115.0f, 20.0f, 15.0f); //X

	pInanimateObjectManager->AddInanimateObjectFence(kFence, 25.0f, 110.0f, 15.0f, 10.0f); //Y

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -30.0f, 165.0f, 40.0f, 15.0f); //Z

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -45.0f, 125.0f, 25.0f, 25.0f); //AA

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -100.0f, 115.0f, 30.0f, 15.0f); //AB

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -105.0f, 75.0f, 25.0f, 25.0f); //AC

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -130.0f, -10.0f, 50.0f, 60.0f); //AD

	pInanimateObjectManager->AddInanimateObjectFence(kFence, -82.5f, -85.0f, 2.5f, 15.0f); //AE

	pInanimateObjectManager->AddInanimateObject(kTownCenterWall, 0.0f, 0.0f, 0.0f );

	pInanimateObjectManager->AddInanimateObject(kGate, 0.0f, 0.0f, 0.0f );

	//Trees for town center
	for ( int k = -50; k < 70; k+=35 )
	{
		pInanimateObjectManager->AddInanimateObject( kTree, (float)k, 0.0f, 80.0f );
	}

	for ( int k = -50; k < 70; k+=35 )
	{
		pInanimateObjectManager->AddInanimateObject( kTree, (float)k, 0.0f, -80.0f );
	}



	//Spawn
	cAnimateObjectManager* pAnimateObjectManager = GetAnimateObjectManager();
	pAnimateObjectManager->CreateVector();

	//Populate Area 1
	for(int i=0; i<3; i++)
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 0);
	}
	//Populate Area 2
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 1);
		pAnimateObjectManager->AddTypeToArea(kZombie, 1);
	}

	//Populate Area 3

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 2);
		pAnimateObjectManager->AddTypeToArea(kHuman, 2);
		pAnimateObjectManager->AddTypeToArea(kZombie, 2);
		pAnimateObjectManager->AddTypeToArea(kHuman, 2);

	}

	//Populate Area 4
	for(int i=0; i<5; i++)
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 3);
	}

	//Populate Area 5
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 4);
		pAnimateObjectManager->AddTypeToArea(kHuman, 4);
		pAnimateObjectManager->AddTypeToArea(kZombie, 4);
		pAnimateObjectManager->AddTypeToArea(kZombie, 4);

	}

	//Populate Area 6
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 5);
		pAnimateObjectManager->AddTypeToArea(kHuman, 5);
		pAnimateObjectManager->AddTypeToArea(kHuman, 5);
		pAnimateObjectManager->AddTypeToArea(kZombie, 5);
	}

	////Populate Area 7
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 6);
		pAnimateObjectManager->AddTypeToArea(kZombie, 6);
	}

	////Populate Area 8
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 7);

		pAnimateObjectManager->AddTypeToArea(kHuman, 7);
		pAnimateObjectManager->AddTypeToArea(kHuman, 7);
	
		pAnimateObjectManager->AddTypeToArea(kZombie, 7);
	}
	//
	////Populate Area 9

	{
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 8);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 8);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 8);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 8);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 8);
		pAnimateObjectManager->AddTypeToArea(kHuman, 8);
		pAnimateObjectManager->AddTypeToArea(kHuman, 8);
	}

	//Populate Area 10
	for(int i=0; i<4; i++)
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 9);
	}

	//Populate Area 11
	for(int i=0; i<3; i++)
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 10);
	}

	//Populate Area 12
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 11);
		pAnimateObjectManager->AddTypeToArea(kHuman, 11);
		pAnimateObjectManager->AddTypeToArea(kHuman, 11);
		pAnimateObjectManager->AddTypeToArea(kZombie, 11);
	}

	////Populate Area 13
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 12);
		pAnimateObjectManager->AddTypeToArea(kHuman, 12);
		pAnimateObjectManager->AddTypeToArea(kZombie, 12);
	}

	//Populate Area 14

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 13);
		pAnimateObjectManager->AddTypeToArea(kHuman, 13);
		pAnimateObjectManager->AddTypeToArea(kZombie, 13);
	}

	////Populate Area 15
	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 14);
		pAnimateObjectManager->AddTypeToArea(kHuman, 14);
	}

	////Populate Area 16

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 15);
		pAnimateObjectManager->AddTypeToArea(kHuman, 15);
		pAnimateObjectManager->AddTypeToArea(kZombie, 15);

	}

	//Populate Area 17

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 15);

		pAnimateObjectManager->AddTypeToArea(kZombie, 15);
		pAnimateObjectManager->AddTypeToArea(kHuman, 16);
		pAnimateObjectManager->AddTypeToArea(kHuman, 16);

	}

	////Populate Area 18
	{
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 17);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 17);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 17);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 17);
		pAnimateObjectManager->AddTypeToArea(kCowZombie, 17);
		pAnimateObjectManager->AddTypeToArea(kHuman, 17);
	}

	////Populate Area 19

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 18);
		pAnimateObjectManager->AddTypeToArea(kZombie, 18);

		pAnimateObjectManager->AddTypeToArea(kHuman, 18);
		pAnimateObjectManager->AddTypeToArea(kHuman, 18);
	}

	//Populate Area 20

	{
		pAnimateObjectManager->AddTypeToArea(kZombie, 19);
		pAnimateObjectManager->AddTypeToArea(kZombie, 19);
		pAnimateObjectManager->AddTypeToArea(kHuman, 19);
	}

	//Populate Area 21

	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 20);
		pAnimateObjectManager->AddTypeToArea(kZombie, 20);
		pAnimateObjectManager->AddTypeToArea(kHuman, 20);
	}

	//Populate Area 22
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 21);
		pAnimateObjectManager->AddTypeToArea(kZombie, 21);


	}

	//Populate Area 23
	for(int i=0; i<3; i++)
	{
		pAnimateObjectManager->AddTypeToArea(kHuman, 22);
	}
}

void ShutdownObjects()
{
	// Doesn't need to do anything right now.
}

//-----------------------------------------------------------------------------
// Desc: Creates all image data needed for the display
void InitDisplay()
{

}

//-----------------------------------------------------------------------------
// Desc: Cleans up any display related state and variables when the application
//		shuts down
void ShutdownDisplay()
{

}

//-----------------------------------------------------------------------------
// Desc: This function carries out any program specific initialization as well
//			as any OpenGL state initialization
void Initialize()
{
	glClearColor(0.69f, 0.77f, 0.87f, 0.0f);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_LIGHTING);
	glShadeModel(GL_FLAT); // GL_SMOOTH

	// turn on ambient and diffuse lighting
	glEnable(GL_LIGHT0);
	GLfloat ambientLight[] = {0.6f, 0.6f, 0.6f, 1.0f };
	GLfloat diffuseLight[] = {0.6f, 0.6f, 0.6f, 1.0f };
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 

	// position the light.
	GLfloat lightPosition[] = {10.0f, 15.0f, 10.0f, 1.0f}; //4th num = argument to function, 0 or 1 - light is at that position or in that direction
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
	
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	// enable depth buffering (so objects get drawn based on depth instead
	// of the raw draw order)
	glEnable(GL_DEPTH_TEST);

	// cull back faces
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
}
